﻿using System;
using System.Drawing;
using System.Windows.Forms;
using CalcSharp.Core.Containers;
using CalcSharp.MDIUI.Dialogs;
using CalcSharp.Core;

namespace CalcSharp.MDIUI
{
    public partial class MatrixEditor : Form
    {
        public string Mname;
        private bool toobig;
        private Bitmap Cache;

        private void InvalidateCache()
        {
            if (Cache != null)
            {
                Cache.Dispose();
                Cache = null;
            }
        }

        public MatrixEditor()
        {
            InitializeComponent();
            Cache = null;
            if (Program.loaded.isCommandAvailable("MTRX_IMG")) colorEfectsToolStripMenuItem.Visible = true;
            Mname = "#noname";
            this.mtrx_name.Text = this.Mname;
            this.Text = "Matrix Editor - " + this.Mname;
        }

        public MatrixEditor(string mname)
        {
            InitializeComponent();
            if (Program.loaded.isCommandAvailable("MTRX_IMG")) colorEfectsToolStripMenuItem.Visible = true;
            this.Mname = mname;
            this.Text = "Matrix Editor - " + this.Mname;
            this.mtrx_name.Text = this.Mname;
            this.drawMtrx(mname);
        }

        private void drawMatrixImage(AMatrix inp)
        {
            if (inp.Rows > 0 && inp.Columns > 0)
            {
                if (Cache == null) Cache = inp.GetPreview();
                previewbox.Image = Cache;
                previewbox.Update();
                previewbox.Refresh();
            }
        }

        private void drawMtrx(string mname)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                mtrx_grid.Rows.Clear();
                mtrx_grid.Columns.Clear();
                AMatrix l = Program.loaded.Mtrx_mem[mname];
                if (l.Rows * l.Columns > 360000)
                {
                    MessageBox.Show("Matrix is too big to be edited by each pixell.");
                    toobig = true;
                }
                else
                {
                    int i, j;
                    for (i = 0; i < l.Columns; i++)
                    {
                        mtrx_grid.Columns.Add(i.ToString(), i.ToString());
                    }
                    for (i = 0; i < l.Rows; i++)
                    {
                        mtrx_grid.Rows.Add();
                        for (j = 0; j < l.Columns; j++)
                        {
                            mtrx_grid.Rows[i].Cells[j].Value = l[i, j];
                        }
                    }
                }
            }
            else
            {
                this.drawMatrixImage(Program.loaded.Mtrx_mem[this.Mname]);
            }
        }

        private void savebtn_Click(object sender, EventArgs e)
        {
            bool waserror = false;
            mtrx_grid.EndEdit();
            try
            {
                AMatrix n = MatrixFuncts.CreateMatrix(mtrx_grid.Rows.Count, mtrx_grid.Columns.Count);
                //DoubleMatrix n = new DoubleMatrix(mtrx_grid.Rows.Count, mtrx_grid.Columns.Count);
                int i, j;
                for (i = 0; i < mtrx_grid.Rows.Count; i++)
                {
                    for (j = 0; j < mtrx_grid.Columns.Count; j++)
                    {
                        n[i, j] = Convert.ToDouble(mtrx_grid[j, i].Value);
                    }
                }
                Program.loaded.Mtrx_mem[Mname] = n;
                this.Text = "Matrix Editor - " + this.Mname;
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.Message, "An error occured:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                waserror = true;
            }
            finally
            {
                if (!waserror) MessageBox.Show("Matrix saved as: " + this.Mname, "Save ok", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void mtrx_name_TextChanged(object sender, EventArgs e)
        {
            this.Mname = mtrx_name.Text;
        }

        private void tabControl1_TabIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 1)
            {
                if (!toobig)
                {
                    if (previewbox.Image != null) previewbox.Image.Dispose();
                    if (mtrx_grid.Columns.Count > 0 && mtrx_grid.Rows.Count > 0)
                    {
                        Bitmap tmp = new Bitmap(mtrx_grid.Columns.Count, mtrx_grid.Rows.Count, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        int i, j;
                        for (i = 0; i < mtrx_grid.Rows.Count; i++)
                        {
                            for (j = 0; j < mtrx_grid.Columns.Count; j++)
                            {
                                if (Convert.ToDouble(mtrx_grid.Rows[i].Cells[j].Value) > int.MaxValue) tmp.SetPixel(j, i, Color.FromArgb(int.MaxValue));
                                else tmp.SetPixel(j, i, Color.FromArgb(Convert.ToInt32(mtrx_grid.Rows[i].Cells[j].Value)));
                            }
                        }
                        previewbox.Image = tmp;
                        previewbox.Update();
                        previewbox.Refresh();
                        //tmp.Dispose();
                        //tmp = null;
                    }
                }
                else
                {
                    this.drawMatrixImage(Program.loaded.Mtrx_mem[this.Mname]);
                }
            }
        }

        private void MatrixEditor_ResizeEnd(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 1 && this.previewbox.Image != null)
            {
                float zoom;
                AMatrix inp = Program.loaded.Mtrx_mem[this.Mname];
                zoom = (previewbox.Height * previewbox.Width) / (inp.Columns * inp.Rows);
                this.Zoomfactor.Text = zoom.ToString() + "%";

            }
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewMatrixDialog dlg = new NewMatrixDialog();
            int i, j;
            dlg.ShowDialog(this);
            if (dlg.DialogResult == DialogResult.OK)
            {
                mtrx_grid.Rows.Clear();
                mtrx_grid.Columns.Clear();
                for (i = 0; i < dlg.Columns; i++)
                {
                    mtrx_grid.Columns.Add(i.ToString(), i.ToString());
                }
                for (i = 0; i < dlg.Rows; i++)
                {
                    mtrx_grid.Rows.Add();
                    for (j = 0; j < dlg.Columns; j++)
                    {
                        mtrx_grid.Rows[i].Cells[j].Value = dlg.InitialValue;
                    }
                }
            }
        }

        private void cropToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MatrixCropDialog dlg = new MatrixCropDialog(Program.loaded.Mtrx_mem[this.Mname]);
            if (MiscCoreFuncts.ShowDialog(dlg) == DialogResult.OK)
            {
                Program.result.matrixtype = MatrixFuncts.Crop(Program.loaded.Mtrx_mem[this.Mname], dlg.RowStart, dlg.ColumnStart, dlg.RowEnd, dlg.ColumnEnd);
                Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
                this.mtrx_name.Text = "#last_mtrx";
                this.drawMtrx(this.Mname);
            }
            this.InvalidateCache();
        }

        private void normalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ResizeMatrixDialog dlg = new ResizeMatrixDialog(Program.loaded.Mtrx_mem[this.Mname]);
            //mtrx_size sizer = new mtrx_size();
            if (MiscCoreFuncts.ShowDialog(dlg) == DialogResult.OK)
            {
                Program.result.matrixtype = MatrixFuncts.Resize(Program.loaded.Mtrx_mem[this.Mname], dlg.Rows, dlg.Columns, false);
                Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
                this.mtrx_name.Text = "#last_mtrx";
                this.drawMtrx(this.Mname);
            }
            this.InvalidateCache();
        }

        private void bilinearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ResizeMatrixDialog dlg = new ResizeMatrixDialog(Program.loaded.Mtrx_mem[this.Mname]);
            if (MiscCoreFuncts.ShowDialog(dlg) == DialogResult.OK)
            {
                Program.result.matrixtype = MatrixFuncts.Resize(Program.loaded.Mtrx_mem[this.Mname], dlg.Rows, dlg.Columns, true);
                Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
                this.mtrx_name.Text = "#last_mtrx";
                this.drawMtrx(this.Mname);
            }
            this.InvalidateCache();
        }

        private void degreesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.result.matrixtype = MatrixFuncts.Rotate(Program.loaded.Mtrx_mem[this.Mname], rottype.pluss90);
            Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
            this.mtrx_name.Text = "#last_mtrx";
            this.drawMtrx(this.Mname);
            this.InvalidateCache();
        }

        private void degreesToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Program.result.matrixtype = MatrixFuncts.Rotate(Program.loaded.Mtrx_mem[this.Mname], rottype.minus90);
            Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
            this.mtrx_name.Text = "#last_mtrx";
            this.drawMtrx(this.Mname);
            this.InvalidateCache();
        }

        private void verticalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.result.matrixtype = MatrixFuncts.Flip(Program.loaded.Mtrx_mem[this.Mname], fliptype.vertical);
            Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
            this.mtrx_name.Text = "#last_mtrx";
            this.drawMtrx(this.Mname);
            this.InvalidateCache();
        }

        private void horizontalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.result.matrixtype = MatrixFuncts.Flip(Program.loaded.Mtrx_mem[this.Mname], fliptype.horizontal);
            Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
            this.mtrx_name.Text = "#last_mtrx";
            this.drawMtrx(this.Mname);
            this.InvalidateCache();
        }

        private void convolutionMatrixAplyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConvolutionEditor cme = new ConvolutionEditor();
            if (MiscCoreFuncts.ShowDialog(cme) == DialogResult.OK)
            {
                Program.result.matrixtype = MatrixFuncts.AplyConvmatrix(Program.loaded.Mtrx_mem[this.Mname], cme.ConvMatrix, cme.Factor, cme.Offset);
                Program.loaded.Mtrx_mem["#last_mtrx"] = Program.result.matrixtype;
                this.mtrx_name.Text = "#last_mtrx";
                this.drawMtrx(this.Mname);
            }
            this.InvalidateCache();
        }

        private void ApplyColorEffect(object sender, EventArgs e)
        {
            ToolStripMenuItem sen = (ToolStripMenuItem)sender;
            switch (sen.Name)
            {
                case "ColorInvert":
                    Program.loaded.ExecCommands("MTRX_IMG INVERT " + this.mtrx_name.Text);
                    this.drawMtrx(this.Mname);
                    break;
            }
            this.InvalidateCache();
        }
    }
}